package cn.wolfcode.car.business.service.impl;

import cn.wolfcode.car.base.domain.User;
import cn.wolfcode.car.business.domain.BpmnInfo;
import cn.wolfcode.car.business.domain.CarPackageAudit;
import cn.wolfcode.car.business.domain.ServiceItem;
import cn.wolfcode.car.business.mapper.ServiceItemMapper;
import cn.wolfcode.car.business.query.ServiceItemQuery;
import cn.wolfcode.car.business.service.IBpmnInfoService;
import cn.wolfcode.car.business.service.ICarPackageAuditService;
import cn.wolfcode.car.business.service.IServiceItemService;
import cn.wolfcode.car.common.base.page.TablePageInfo;
import cn.wolfcode.car.common.exception.BusinessException;
import cn.wolfcode.car.common.util.Convert;
import cn.wolfcode.car.common.web.AjaxResult;
import cn.wolfcode.car.shiro.ShiroUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.github.pagehelper.PageHelper;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Service
@Transactional
public class ServiceItemServiceImpl extends ServiceImpl<ServiceItemMapper, ServiceItem> implements IServiceItemService {

    @Resource
    private ServiceItemMapper serviceItemMapper;
    @Autowired
    private ICarPackageAuditService carPackageAuditService;
    @Autowired
    private IBpmnInfoService bpmnInfoService;
    @Autowired
    private RuntimeService runtimeService;

    /*
     select id, name, original_price, discount_price, car_package, info, create_time,
           service_catalog, audit_status, sale_status
    from bus_service_item
    <where>
      <if test="name != null and '' != name">
        and name like concat('%',#{name},'%')
      </if>
     <if test="carPackage != null">
       and car_package = ${carPackage}
     </if>
    <if test="serviceCatalog != null">
      and service_catalog = ${serviceCatalog}
    </if>
    <if test="auditStatus != null">
      and audit_status = ${auditStatus}
    </if>
    <if test="saleStatus != null">
      and sale_status = ${saleStatus}
    </if>
     */
    @Override
    public TablePageInfo<ServiceItem> query(ServiceItemQuery qo) {
        IPage<ServiceItem> page = new Page<>(qo.getPageNum(), qo.getPageSize());
        LambdaQueryWrapper<ServiceItem> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(!qo.getName().trim().isEmpty(), ServiceItem::getName, qo.getName())
                .eq(qo.getCarPackage() != null, ServiceItem::getCarPackage, qo.getCarPackage())
                .eq(qo.getServiceCatalog() != null, ServiceItem::getServiceCatalog, qo.getServiceCatalog())
                .eq(qo.getAuditStatus() != null, ServiceItem::getAuditStatus, qo.getAuditStatus())
                .eq(qo.getSaleStatus() != null, ServiceItem::getSaleStatus, qo.getSaleStatus());
        return new TablePageInfo<>(super.page(page, wrapper));
    }


    @Override
    public boolean save(ServiceItem serviceItem) {
        if (serviceItem.getCarPackage() == ServiceItem.CARPACKAGE_YES) {
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        } else {
            serviceItem.setAuditStatus(ServiceItem.AUDITSTATUS_NO_REQUIRED);
        }
        serviceItem.setSaleStatus(ServiceItem.SALESTATUS_OFF);
        serviceItem.setCreateTime(new Date());
        serviceItemMapper.insert(serviceItem);
        return true;
    }

    @Override
    public ServiceItem get(Long id) {
        return serviceItemMapper.selectById(id);
    }


    @Override
    public void update(ServiceItem serviceItem) {
        ServiceItem item = get(serviceItem.getId());
        //如果是上架状态，不允许修改
        if (item.getSaleStatus().equals(ServiceItem.SALESTATUS_ON)) {
            throw new BusinessException("该任务处于上架状态，不允许修改");
            //如果是下架状态，而且是套餐是审核中，则不可以修改
        } else if (item.getSaleStatus().equals(ServiceItem.SALESTATUS_OFF) && item.getAuditStatus().equals(ServiceItem.AUDITSTATUS_AUDITING)) {
            throw new BusinessException("套餐正在审核中，不能进行编辑操作");
            //如果套餐审核通过，进行初始化操作
        } else if (serviceItem.getAuditStatus() == ServiceItem.AUDITSTATUS_APPROVED) {
            item.setAuditStatus(ServiceItem.AUDITSTATUS_INIT);
        }
        serviceItemMapper.updateById(serviceItem);
    }

    @Override
    public void deleteBatch(String ids) {
        Long[] dictIds = Convert.toLongArray(ids);
        for (Long dictId : dictIds) {
            serviceItemMapper.deleteById(dictId);
        }
    }

    @Override
    public List<ServiceItem> list() {
        return serviceItemMapper.selectList(null);
    }

    @Override
    public void saleOn(Long id) {
        ServiceItem serviceItem = get(id);
        //如果是套餐，不是审核通过，则该服务项不能上架
        if (serviceItem.getCarPackage().equals(ServiceItem.CARPACKAGE_YES) && !serviceItem.getAuditStatus().equals(ServiceItem.AUDITSTATUS_APPROVED)) {
            throw new BusinessException("该套餐服务还未审核通过，暂时不能上架");
        }
        // update bus_service_item set sale_status = #{salestatusOn} where id = #{id}
        LambdaUpdateWrapper<ServiceItem> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ServiceItem::getId, id).set(ServiceItem::getSaleStatus, ServiceItem.SALESTATUS_ON);
        serviceItemMapper.update(null, wrapper);
    }

    @Override
    public void saleOff(Long id) {
        // update bus_service_item set sale_status = #{salestatusOn} where id = #{id}
        LambdaUpdateWrapper<ServiceItem> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ServiceItem::getId, id).set(ServiceItem::getSaleStatus, ServiceItem.SALESTATUS_OFF);
        serviceItemMapper.update(null, wrapper);
    }

    @Override
    @Transactional
    public void startAudit(Long id, Long bpmnInfoId, Long director, Long finance, String info) {
        ServiceItem serviceItem = this.get(id);
        //只有在服务套餐审核中的时候才可以发起审核
        if (serviceItem == null || serviceItem.getAuditStatus() != ServiceItem.AUDITSTATUS_INIT) {
            throw new BusinessException("非法操作");
        }
        //修改审核状态，修改为审核中
        //update bus_service_item set audit_status = #{status} where id = #{serviceItemId}
        LambdaUpdateWrapper<ServiceItem> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ServiceItem::getId, id).set(ServiceItem::getAuditStatus, ServiceItem.AUDITSTATUS_AUDITING);
        serviceItemMapper.update(null, wrapper);
        CarPackageAudit carPackageAudit = new CarPackageAudit();
        //设置登录的用户发起者
        carPackageAudit.setCreator(ShiroUtils.getUser().getUserName());
        //设置服务项目信息
        carPackageAudit.setServiceItemInfo(serviceItem.getInfo());
        //设置服务项目 ID
        carPackageAudit.setServiceItemId(id);
        //设置创建的时间
        carPackageAudit.setCreateTime(new Date());
        //设置项目的名称
        carPackageAudit.setServiceItemName(serviceItem.getName());
        //设置当前节点的审核人
        carPackageAudit.setAuditorId(director);
        //设置Bpmn的id
        carPackageAudit.setBpmnInfoId(bpmnInfoId);
        //设置服务项目价格
        carPackageAudit.setServiceItemPrice(serviceItem.getDiscountPrice());
        //设置备注信息
        carPackageAudit.setInfo(info);
        //保存审核的对象
        carPackageAuditService.save(carPackageAudit);

        //启动流程
        //获取BpmnInfo对象
        BpmnInfo bpmnInfo = bpmnInfoService.get(bpmnInfoId);
        Map<String, Object> map = new HashMap<>();
        if (director != null) map.put("director", director.toString());
        if (finance != null) map.put("finance", finance.toString());
        map.put("discountPrice", serviceItem.getDiscountPrice().longValue());
        //启动流程实例
        ProcessInstance processInstance = runtimeService.startProcessInstanceByKey(bpmnInfo.getActProcessKey(), carPackageAudit.getId().toString(), map);
        carPackageAudit.setInstanceId(processInstance.getId());
        carPackageAuditService.update(carPackageAudit);
    }

    @Override
    @Transactional
    public void changeAuditStatus(Long serviceItemId, Integer status) {
        //update bus_service_item set audit_status = #{status} where id = #{serviceItemId}
        LambdaUpdateWrapper<ServiceItem> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(ServiceItem::getId, serviceItemId).set(ServiceItem::getAuditStatus, status);
        serviceItemMapper.update(null, wrapper);
    }
}
